/**
 * 数据验证工具类
 */

import { ApiError } from './response';

/**
 * 验证规则接口
 */
export interface ValidationRule {
  required?: boolean;
  type?: 'string' | 'number' | 'boolean' | 'email' | 'url' | 'array' | 'object';
  minLength?: number;
  maxLength?: number;
  min?: number;
  max?: number;
  pattern?: RegExp;
  custom?: (value: any) => boolean | string;
  message?: string;
}

/**
 * 验证规则集合
 */
export interface ValidationSchema {
  [key: string]: ValidationRule;
}

/**
 * 验证结果
 */
export interface ValidationResult {
  isValid: boolean;
  errors: { [key: string]: string };
}

/**
 * 数据验证器
 */
export class Validator {
  /**
   * 验证单个字段
   */
  static validateField(value: any, rule: ValidationRule, fieldName: string): string | null {
    // 必填验证
    if (rule.required && (value === undefined || value === null || value === '')) {
      return rule.message || `${fieldName}不能为空`;
    }

    // 如果值为空且非必填，跳过其他验证
    if (!rule.required && (value === undefined || value === null || value === '')) {
      return null;
    }

    // 类型验证
    if (rule.type) {
      const typeError = this.validateType(value, rule.type, fieldName);
      if (typeError) return typeError;
    }

    // 长度验证（字符串和数组）
    if (typeof value === 'string' || Array.isArray(value)) {
      if (rule.minLength !== undefined && value.length < rule.minLength) {
        return rule.message || `${fieldName}长度不能少于${rule.minLength}`;
      }
      if (rule.maxLength !== undefined && value.length > rule.maxLength) {
        return rule.message || `${fieldName}长度不能超过${rule.maxLength}`;
      }
    }

    // 数值范围验证
    if (typeof value === 'number') {
      if (rule.min !== undefined && value < rule.min) {
        return rule.message || `${fieldName}不能小于${rule.min}`;
      }
      if (rule.max !== undefined && value > rule.max) {
        return rule.message || `${fieldName}不能大于${rule.max}`;
      }
    }

    // 正则表达式验证
    if (rule.pattern && typeof value === 'string') {
      if (!rule.pattern.test(value)) {
        return rule.message || `${fieldName}格式不正确`;
      }
    }

    // 自定义验证
    if (rule.custom) {
      const customResult = rule.custom(value);
      if (typeof customResult === 'string') {
        return customResult;
      }
      if (customResult === false) {
        return rule.message || `${fieldName}验证失败`;
      }
    }

    return null;
  }

  /**
   * 类型验证
   */
  private static validateType(value: any, type: string, fieldName: string): string | null {
    switch (type) {
      case 'string':
        if (typeof value !== 'string') {
          return `${fieldName}必须是字符串类型`;
        }
        break;
      case 'number':
        if (typeof value !== 'number' || isNaN(value)) {
          return `${fieldName}必须是数字类型`;
        }
        break;
      case 'boolean':
        if (typeof value !== 'boolean') {
          return `${fieldName}必须是布尔类型`;
        }
        break;
      case 'email':
        if (typeof value !== 'string' || !this.isValidEmail(value)) {
          return `${fieldName}必须是有效的邮箱地址`;
        }
        break;
      case 'url':
        if (typeof value !== 'string' || !this.isValidUrl(value)) {
          return `${fieldName}必须是有效的URL地址`;
        }
        break;
      case 'array':
        if (!Array.isArray(value)) {
          return `${fieldName}必须是数组类型`;
        }
        break;
      case 'object':
        if (typeof value !== 'object' || value === null || Array.isArray(value)) {
          return `${fieldName}必须是对象类型`;
        }
        break;
    }
    return null;
  }

  /**
   * 验证数据对象
   */
  static validate(data: any, schema: ValidationSchema): ValidationResult {
    const errors: { [key: string]: string } = {};

    for (const [fieldName, rule] of Object.entries(schema)) {
      const value = data[fieldName];
      const error = this.validateField(value, rule, fieldName);
      if (error) {
        errors[fieldName] = error;
      }
    }

    return {
      isValid: Object.keys(errors).length === 0,
      errors
    };
  }

  /**
   * 验证并抛出错误
   */
  static validateAndThrow(data: any, schema: ValidationSchema): void {
    const result = this.validate(data, schema);
    if (!result.isValid) {
      const errorMessages = Object.values(result.errors);
      throw ApiError.validation(errorMessages[0], result.errors);
    }
  }

  /**
   * 邮箱格式验证
   */
  private static isValidEmail(email: string): boolean {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return emailRegex.test(email);
  }

  /**
   * URL格式验证
   */
  private static isValidUrl(url: string): boolean {
    try {
      new URL(url);
      return true;
    } catch {
      return false;
    }
  }

  /**
   * 手机号格式验证
   */
  static isValidPhone(phone: string): boolean {
    const phoneRegex = /^1[3-9]\d{9}$/;
    return phoneRegex.test(phone);
  }

  /**
   * 身份证号格式验证
   */
  static isValidIdCard(idCard: string): boolean {
    const idCardRegex = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
    return idCardRegex.test(idCard);
  }

  /**
   * 密码强度验证
   */
  static validatePasswordStrength(password: string): { isValid: boolean; message?: string } {
    if (password.length < 6) {
      return { isValid: false, message: '密码长度不能少于6位' };
    }
    if (password.length > 20) {
      return { isValid: false, message: '密码长度不能超过20位' };
    }
    if (!/[a-zA-Z]/.test(password)) {
      return { isValid: false, message: '密码必须包含字母' };
    }
    if (!/\d/.test(password)) {
      return { isValid: false, message: '密码必须包含数字' };
    }
    return { isValid: true };
  }

  /**
   * 用户名格式验证
   */
  static validateUsername(username: string): { isValid: boolean; message?: string } {
    if (username.length < 3) {
      return { isValid: false, message: '用户名长度不能少于3位' };
    }
    if (username.length > 20) {
      return { isValid: false, message: '用户名长度不能超过20位' };
    }
    if (!/^[a-zA-Z0-9_]+$/.test(username)) {
      return { isValid: false, message: '用户名只能包含字母、数字和下划线' };
    }
    return { isValid: true };
  }
}

/**
 * 常用验证规则
 */
export const CommonValidationRules = {
  // 用户相关
  username: {
    required: true,
    type: 'string' as const,
    minLength: 3,
    maxLength: 20,
    pattern: /^[a-zA-Z0-9_]+$/,
    message: '用户名长度3-20位，只能包含字母、数字和下划线'
  },
  password: {
    required: true,
    type: 'string' as const,
    minLength: 6,
    maxLength: 20,
    message: '密码长度6-20位'
  },
  email: {
    required: true,
    type: 'email' as const,
    message: '请输入有效的邮箱地址'
  },
  phone: {
    type: 'string' as const,
    pattern: /^1[3-9]\d{9}$/,
    message: '请输入有效的手机号码'
  },

  // 产品相关
  productTitle: {
    required: true,
    type: 'string' as const,
    minLength: 1,
    maxLength: 100,
    message: '产品标题长度1-100字符'
  },
  productContent: {
    type: 'string' as const,
    maxLength: 5000,
    message: '产品内容不能超过5000字符'
  },
  price: {
    type: 'number' as const,
    min: 0,
    message: '价格不能为负数'
  },

  // 案例相关
  caseTitle: {
    required: true,
    type: 'string' as const,
    minLength: 1,
    maxLength: 100,
    message: '案例标题长度1-100字符'
  },
  caseDescription: {
    type: 'string' as const,
    maxLength: 2000,
    message: '案例描述不能超过2000字符'
  },

  // 联系人相关
  contactName: {
    required: true,
    type: 'string' as const,
    minLength: 1,
    maxLength: 50,
    message: '联系人姓名长度1-50字符'
  },
  contactPosition: {
    type: 'string' as const,
    maxLength: 50,
    message: '职位不能超过50字符'
  },

  // 通用
  id: {
    required: true,
    type: 'string' as const,
    minLength: 1,
    message: 'ID不能为空'
  },
  sort: {
    type: 'number' as const,
    min: 0,
    message: '排序值不能为负数'
  },
  status: {
    type: 'string' as const,
    custom: (value: string) => ['active', 'inactive'].includes(value),
    message: '状态值必须是active或inactive'
  },
  role: {
    type: 'string' as const,
    custom: (value: string) => ['admin', 'editor', 'guest'].includes(value),
    message: '角色必须是admin、editor或guest'
  }
};